home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Contact_Vcard_Parse.php < prev    next >
PHP Script  |  2004-03-24  |  26KB  |  836 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */ 
  3. // +----------------------------------------------------------------------+ 
  4. // | PHP version 4                                                        | 
  5. // +----------------------------------------------------------------------+ 
  6. // | Copyright (c) 1997-2002 The PHP Group                                | 
  7. // +----------------------------------------------------------------------+ 
  8. // | This source file is subject to version 2.0 of the PHP license,       | 
  9. // | that is bundled with this package in the file LICENSE, and is        | 
  10. // | available at through the world-wide-web at                           | 
  11. // | http://www.php.net/license/2_02.txt.                                 | 
  12. // | If you did not receive a copy of the PHP license and are unable to   | 
  13. // | obtain it through the world-wide-web, please send a note to          | 
  14. // | license@php.net so we can mail you a copy immediately.               | 
  15. // +----------------------------------------------------------------------+ 
  16. // | Authors: Paul M. Jones <pmjones@ciaweb.net>                          | 
  17. // +----------------------------------------------------------------------+ 
  18. // 
  19. // $Id: Contact_Vcard_Parse.php,v 1.4 2004/02/18 21:41:13 pmjones Exp $ 
  20.  
  21.  
  22. /**
  23. * Parser for vCards.
  24. *
  25. * This class parses vCard 2.1 and 3.0 sources from file or text into a
  26. * structured array.
  27. * Usage:
  28. * <code>
  29. *     // include this class file
  30. *     require_once 'Contact_Vcard_Parse.php';
  31. *     
  32. *     // instantiate a parser object
  33. *     $parse = new Contact_Vcard_Parse();
  34. *     
  35. *     // parse a vCard file and store the data
  36. *     // in $cardinfo
  37. *     $cardinfo = $parse->fromFile('sample.vcf');
  38. *     
  39. *     // view the card info array
  40. *     echo '<pre>';
  41. *     print_r($cardinfo);
  42. *     echo '</pre>';
  43. * </code>
  44. *
  45. * @author Paul M. Jones <pmjones@ciaweb.net>
  46. * @package Contact_Vcard_Parse
  47. * @version 1.30
  48. */
  49.  
  50. class Contact_Vcard_Parse {
  51.     
  52.     
  53.     /**
  54.     * 
  55.     * Reads a file for parsing, then sends it to $this->fromText()
  56.     * and returns the results.
  57.     * 
  58.     * @access public
  59.     * 
  60.     * @param array $filename The filename to read for vCard information.
  61.     * 
  62.     * @return array An array of of vCard information extracted from the
  63.     * file.
  64.     * 
  65.     * @see Contact_Vcard_Parse::fromText()
  66.     * 
  67.     * @see Contact_Vcard_Parse::_fromArray()
  68.     * 
  69.     */
  70.     
  71.     function fromFile($filename, $decode_qp = true)
  72.     {
  73.         $text = $this->fileGetContents($filename);
  74.         
  75.         if ($text === false) {
  76.             return false;
  77.         } else {
  78.             // dump to, and get return from, the fromText() method.
  79.             return $this->fromText($text, $decode_qp);
  80.         }
  81.     }
  82.     
  83.     
  84.     /**
  85.     * 
  86.     * Reads the contents of a file.  Included for users whose PHP < 4.3.0.
  87.     * 
  88.     * @access public
  89.     * 
  90.     * @param array $filename The filename to read for vCard information.
  91.     * 
  92.     * @return string|bool The contents of the file if it exists and is
  93.     * readable, or boolean false if not.
  94.     * 
  95.     * @see Contact_Vcard_Parse::fromFile()
  96.     * 
  97.     */
  98.     
  99.     function fileGetContents($filename)
  100.     {
  101.         if (file_exists($filename) &&
  102.             is_readable($filename)) {
  103.             
  104.             $text = '';
  105.             $len = filesize($filename);
  106.             
  107.             $fp = fopen($filename, 'r');
  108.             while ($line = fread($fp, filesize($filename))) {
  109.                 $text .= $line;
  110.             }
  111.             fclose($fp);
  112.             
  113.             return $text;
  114.             
  115.         } else {
  116.         
  117.             return false;
  118.             
  119.         }
  120.     }
  121.     
  122.     
  123.     /**
  124.     * 
  125.     * Prepares a block of text for parsing, then sends it through and
  126.     * returns the results from $this->fromArray().
  127.     * 
  128.     * @access public
  129.     * 
  130.     * @param array $text A block of text to read for vCard information.
  131.     * 
  132.     * @return array An array of vCard information extracted from the
  133.     * source text.
  134.     * 
  135.     * @see Contact_Vcard_Parse::_fromArray()
  136.     * 
  137.     */
  138.     
  139.     function fromText($text, $decode_qp = true)
  140.     {
  141.         // convert all kinds of line endings to Unix-standard and get
  142.         // rid of double blank lines.
  143.         $this->convertLineEndings($text);
  144.         
  145.         // unfold lines.  concat two lines where line 1 ends in \n and
  146.         // line 2 starts with a whitespace character.  only removes
  147.         // the first whitespace character, leaves others in place.
  148.         $fold_regex = '(\n)([ |\t])';
  149.         $text = preg_replace("/$fold_regex/i", "", $text);
  150.         
  151.         // massage for Macintosh OS X Address Book (remove nulls that
  152.         // Address Book puts in for unicode chars)
  153.         $text = str_replace("\x00", '', $text);
  154.         
  155.         // convert the resulting text to an array of lines
  156.         $lines = explode("\n", $text);
  157.         
  158.         // parse the array of lines and return vCard info
  159.         return $this->_fromArray($lines, $decode_qp);
  160.     }
  161.     
  162.     
  163.     /**
  164.     * 
  165.     * Converts line endings in text.
  166.     * 
  167.     * Takes any text block and converts all line endings to UNIX
  168.     * standard. DOS line endings are \r\n, Mac are \r, and UNIX is \n.
  169.     *
  170.     * NOTE: Acts on the text block in-place; does not return a value.
  171.     * 
  172.     * @access public
  173.     * 
  174.     * @param string $text The string on which to convert line endings.
  175.     * 
  176.     * @return void
  177.     * 
  178.     */
  179.     
  180.     function convertLineEndings(&$text)
  181.     {
  182.         // DOS
  183.         $text = str_replace("\r\n", "\n", $text);
  184.         
  185.         // Mac
  186.         $text = str_replace("\r", "\n", $text);
  187.     }
  188.     
  189.     
  190.     /**
  191.     * 
  192.     * Splits a string into an array at semicolons.  Honors backslash-
  193.     * escaped semicolons (i.e., splits at ';' not '\;').
  194.     * 
  195.     * @access public
  196.     * 
  197.     * @param string $text The string to split into an array.
  198.     * 
  199.     * @param bool $convertSingle If splitting the string results in a
  200.     * single array element, return a string instead of a one-element
  201.     * array.
  202.     * 
  203.     * @return mixed An array of values, or a single string.
  204.     * 
  205.     */
  206.     
  207.     function splitBySemi($text, $convertSingle = false)
  208.     {
  209.         // we use these double-backs (\\) because they get get converted
  210.         // to single-backs (\) by preg_split.  the quad-backs (\\\\) end
  211.         // up as as double-backs (\\), which is what preg_split requires
  212.         // to indicate a single backslash (\). what a mess.
  213.         $regex = '(?<!\\\\)(\;)';
  214.         $tmp = preg_split("/$regex/i", $text);
  215.         
  216.         // if there is only one array-element and $convertSingle is
  217.         // true, then return only the value of that one array element
  218.         // (instead of returning the array).
  219.         if ($convertSingle && count($tmp) == 1) {
  220.             return $tmp[0];
  221.         } else {
  222.             return $tmp;
  223.         }
  224.     }
  225.     
  226.     
  227.     /**
  228.     * 
  229.     * Splits a string into an array at commas.  Honors backslash-
  230.     * escaped commas (i.e., splits at ',' not '\,').
  231.     * 
  232.     * @access public
  233.     * 
  234.     * @param string $text The string to split into an array.
  235.     * 
  236.     * @param bool $convertSingle If splitting the string results in a
  237.     * single array element, return a string instead of a one-element
  238.     * array.
  239.     * 
  240.     * @return mixed An array of values, or a single string.
  241.     * 
  242.     */
  243.     
  244.     function splitByComma($text, $convertSingle = false)
  245.     {
  246.         // we use these double-backs (\\) because they get get converted
  247.         // to single-backs (\) by preg_split.  the quad-backs (\\\\) end
  248.         // up as as double-backs (\\), which is what preg_split requires
  249.         // to indicate a single backslash (\). ye gods, how ugly.
  250.         $regex = '(?<!\\\\)(\,)';
  251.         $tmp = preg_split("/$regex/i", $text);
  252.         
  253.         // if there is only one array-element and $convertSingle is
  254.         // true, then return only the value of that one array element
  255.         // (instead of returning the array).
  256.         if ($convertSingle && count($tmp) == 1) {
  257.             return $tmp[0];
  258.         } else {
  259.             return $tmp;
  260.         }
  261.     }
  262.     
  263.     
  264.     /**
  265.     * 
  266.     * Used to make string human-readable after being a vCard value.
  267.     * 
  268.     * Converts...
  269.     *     \; => ;
  270.     *     \, => ,
  271.     *     literal \n => newline
  272.     * 
  273.     * @access public
  274.     * 
  275.     * @param mixed $text The text to unescape.
  276.     * 
  277.     * @return void
  278.     * 
  279.     */
  280.     
  281.     function unescape(&$text)
  282.     {
  283.         if (is_array($text)) {
  284.             foreach ($text as $key => $val) {
  285.                 $this->unescape($val);
  286.                 $text[$key] = $val;
  287.             }
  288.         } else {
  289.             $text = str_replace('\;', ';', $text);
  290.             $text = str_replace('\,', ',', $text);
  291.             $text = str_replace('\n', "\n", $text);
  292.         }
  293.     }
  294.     
  295.     
  296.     /**
  297.     *
  298.     * Emulated destructor.
  299.     *
  300.     * @access private
  301.     * @return boolean true
  302.     *
  303.     */
  304.     
  305.     function _Contact_Vcard_Parse()
  306.     {
  307.         return true;
  308.     }
  309.     
  310.     
  311.     /**
  312.     * 
  313.     * Parses an array of source lines and returns an array of vCards.
  314.     * Each element of the array is itself an array expressing the types,
  315.     * parameters, and values of each part of the vCard. Processes both
  316.     * 2.1 and 3.0 vCard sources.
  317.     *
  318.     * @access private
  319.     * 
  320.     * @param array $source An array of lines to be read for vCard
  321.     * information.
  322.     * 
  323.     * @return array An array of of vCard information extracted from the
  324.     * source array.
  325.     * 
  326.     */
  327.     
  328.     function _fromArray($source, $decode_qp = true)
  329.     {
  330.         // the info array will hold all resulting vCard information.
  331.         $info = array();
  332.         
  333.         // tells us whether the source text indicates the beginning of a
  334.         // new vCard with a BEGIN:VCARD tag.
  335.         $begin = false;
  336.         
  337.         // holds information about the current vCard being read from the
  338.         // source text.
  339.         $card = array();
  340.         
  341.         // loop through each line in the source array
  342.         foreach ($source as $line) {
  343.             
  344.             // if the line is blank, skip it.
  345.             if (trim($line) == '') {
  346.                 continue;
  347.             }
  348.             
  349.             // find the first instance of ':' on the line.  The part
  350.             // to the left of the colon is the type and parameters;
  351.             // the part to the right of the colon is the value data.
  352.             $pos = strpos($line, ':');
  353.             
  354.             // if there is no colon, skip the line.
  355.             if ($pos === false) {
  356.                 continue;
  357.             }
  358.             
  359.             // get the left and right portions
  360.             $left = trim(substr($line, 0, $pos));
  361.             $right = trim(substr($line, $pos+1, strlen($line)));
  362.             
  363.             // have we started yet?
  364.             if (! $begin) {
  365.                 
  366.                 // nope.  does this line indicate the beginning of
  367.                 // a new vCard?
  368.                 if (strtoupper($left) == 'BEGIN' &&
  369.                     strtoupper($right) == 'VCARD') {
  370.                     
  371.                     // tell the loop that we've begun a new card
  372.                     $begin = true;
  373.                 }
  374.                 
  375.                 // regardless, loop to the next line of source. if begin
  376.                 // is still false, the next loop will check the line. if
  377.                 // begin has now been set to true, the loop will start
  378.                 // collecting card info.
  379.                 continue;
  380.                 
  381.             } else {
  382.                 
  383.                 // yep, we've started, but we don't know how far along
  384.                 // we are in the card. is this the ending line of the
  385.                 // current vCard?
  386.                 if (strtoupper($left) == 'END' &&
  387.                     strtoupper($right) == 'VCARD') {
  388.                     
  389.                     // yep, we're done. keep the info from the current
  390.                     // card...
  391.                     $info[] = $card;
  392.                     
  393.                     // ...and reset to grab a new card if one exists in
  394.                     // the source array.
  395.                     $begin = false;
  396.                     $card = array();
  397.                     
  398.                 } else {
  399.                     
  400.                     // we're not on an ending line, so collect info from
  401.                     // this line into the current card. split the
  402.                     // left-portion of the line into a type-definition
  403.                     // (the kind of information) and parameters for the
  404.                     // type.
  405.                     $typedef = $this->_getTypeDef($left);
  406.                     $params = $this->_getParams($left);
  407.                     
  408.                     // if we are decoding quoted-printable, do so now.
  409.                     // QUOTED-PRINTABLE is not allowed in version 3.0,
  410.                     // but we don't check for versioning, so we do it
  411.                     // regardless.  ;-)
  412.                     $this->_decode_qp($params, $right);
  413.                     
  414.                     // now get the value-data from the line, based on
  415.                     // the typedef
  416.                     switch ($typedef) {
  417.                         
  418.                     case 'N':
  419.                         // structured name of the person
  420.                         $value = $this->_parseN($right);
  421.                         break;
  422.                         
  423.                     case 'ADR':
  424.                         // structured address of the person
  425.                         $value = $this->_parseADR($right);
  426.                         break;
  427.                         
  428.                     case 'NICKNAME':
  429.                         // nicknames
  430.                         $value = $this->_parseNICKNAME($right);
  431.                         break;
  432.                         
  433.                     case 'ORG':
  434.                         // organizations the person belongs to
  435.                         $value = $this->_parseORG($right);
  436.                         break;
  437.                         
  438.                     case 'CATEGORIES':
  439.                         // categories to which this card is assigned
  440.                         $value = $this->_parseCATEGORIES($right);
  441.                         break;
  442.                         
  443.                     case 'GEO':
  444.                         // geographic coordinates
  445.                         $value = $this->_parseGEO($right);
  446.                         break;
  447.                         
  448.                     default:
  449.                         // by default, just grab the plain value. keep
  450.                         // as an array to make sure *all* values are
  451.                         // arrays.  for consistency. ;-)
  452.                         $value = array(array($right));
  453.                         break;
  454.                     }
  455.                     
  456.                     // add the type, parameters, and value to the
  457.                     // current card array.  note that we allow multiple
  458.                     // instances of the same type, which might be dumb
  459.                     // in some cases (e.g., N).
  460.                     $card[$typedef][] = array(
  461.                         'param' => $params,
  462.                         'value' => $value
  463.                     );
  464.                 }
  465.             }
  466.         }
  467.         
  468.         $this->unescape($info);
  469.         return $info;
  470.     }
  471.     
  472.     
  473.     /**
  474.     *
  475.     * Takes a vCard line and extracts the Type-Definition for the line.
  476.     * 
  477.     * @access private
  478.     *
  479.     * @param string $text A left-part (before-the-colon part) from a
  480.     * vCard line.
  481.     * 
  482.     * @return string The type definition for the line.
  483.     * 
  484.     */
  485.     
  486.     function _getTypeDef($text)
  487.     {
  488.         // split the text by semicolons
  489.         $split = $this->splitBySemi($text);
  490.         
  491.         // only return first element (the typedef)
  492.         return $split[0];
  493.     }
  494.     
  495.     
  496.     /**
  497.     *
  498.     * Finds the Type-Definition parameters for a vCard line.
  499.     * 
  500.     * @access private
  501.     * 
  502.     * @param string $text A left-part (before-the-colon part) from a
  503.     * vCard line.
  504.     * 
  505.     * @return mixed An array of parameters.
  506.     * 
  507.     */
  508.     
  509.     function _getParams($text)
  510.     {
  511.         // split the text by semicolons into an array
  512.         $split = $this->splitBySemi($text);
  513.         
  514.         // drop the first element of the array (the type-definition)
  515.         array_shift($split);
  516.         
  517.         // set up an array to retain the parameters, if any
  518.         $params = array();
  519.         
  520.         // loop through each parameter.  the params may be in the format...
  521.         // "TYPE=type1,type2,type3"
  522.         //    ...or...
  523.         // "TYPE=type1;TYPE=type2;TYPE=type3"
  524.         foreach ($split as $full) {
  525.             
  526.             // split the full parameter at the equal sign so we can tell
  527.             // the parameter name from the parameter value
  528.             $tmp = explode("=", $full);
  529.             
  530.             // the key is the left portion of the parameter (before
  531.             // '='). if in 2.1 format, the key may in fact be the
  532.             // parameter value, not the parameter name.
  533.             $key = strtoupper(trim($tmp[0]));
  534.             
  535.             // get the parameter name by checking to see if it's in
  536.             // vCard 2.1 or 3.0 format.
  537.             $name = $this->_getParamName($key);
  538.             
  539.             // list of all parameter values
  540.             $listall = trim($tmp[1]);
  541.             
  542.             // if there is a value-list for this parameter, they are
  543.             // separated by commas, so split them out too.
  544.             $list = $this->splitByComma($listall);
  545.             
  546.             // now loop through each value in the parameter and retain
  547.             // it.  if the value is blank, that means it's a 2.1-style
  548.             // param, and the key itself is the value.
  549.             foreach ($list as $val) {
  550.                 if (trim($val) != '') {
  551.                     // 3.0 formatted parameter
  552.                     $params[$name][] = trim($val);
  553.                 } else {
  554.                     // 2.1 formatted parameter
  555.                     $params[$name][] = $key;
  556.                 }
  557.             }
  558.             
  559.             // if, after all this, there are no parameter values for the
  560.             // parameter name, retain no info about the parameter (saves
  561.             // ram and checking-time later).
  562.             if (count($params[$name]) == 0) {
  563.                 unset($params[$name]);
  564.             }
  565.         }
  566.         
  567.         // return the parameters array.
  568.         return $params;
  569.     }
  570.     
  571.     
  572.     /**
  573.     *
  574.     * Looks at the parameters of a vCard line; if one of them is
  575.     * ENCODING[] => QUOTED-PRINTABLE then decode the text in-place.
  576.     * 
  577.     * @access private
  578.     * 
  579.     * @param array $params A parameter array from a vCard line.
  580.     * 
  581.     * @param string $text A right-part (after-the-colon part) from a
  582.     * vCard line.
  583.     *
  584.     * @return void
  585.     * 
  586.     */
  587.     
  588.     function _decode_qp(&$params, &$text)
  589.     {
  590.         // loop through each parameter
  591.         foreach ($params as $param_key => $param_val) {
  592.             
  593.             // check to see if it's an encoding param
  594.             if (trim(strtoupper($param_key)) == 'ENCODING') {
  595.             
  596.                 // loop through each encoding param value
  597.                 foreach ($param_val as $enc_key => $enc_val) {
  598.                 
  599.                     // if any of the values are QP, decode the text
  600.                     // in-place and return
  601.                     if (trim(strtoupper($enc_val)) == 'QUOTED-PRINTABLE') {
  602.                         $text = quoted_printable_decode($text);
  603.                         return;
  604.                     }
  605.                 }
  606.             }
  607.         }
  608.     }
  609.     
  610.     
  611.     /**
  612.     * 
  613.     * Returns parameter names from 2.1-formatted vCards.
  614.     *
  615.     * The vCard 2.1 specification allows parameter values without a
  616.     * name. The parameter name is then determined from the unique
  617.     * parameter value.
  618.     * 
  619.     * Shamelessly lifted from Frank Hellwig <frank@hellwig.org> and his
  620.     * vCard PHP project <http://vcardphp.sourceforge.net>.
  621.     * 
  622.     * @access private
  623.     * 
  624.     * @param string $value The first element in a parameter name-value
  625.     * pair.
  626.     * 
  627.     * @return string The proper parameter name (TYPE, ENCODING, or
  628.     * VALUE).
  629.     * 
  630.     */
  631.      
  632.     function _getParamName($value)
  633.     {
  634.         static $types = array (
  635.             'DOM', 'INTL', 'POSTAL', 'PARCEL','HOME', 'WORK',
  636.             'PREF', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER',
  637.             'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO',
  638.             'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD',
  639.             'INTERNET', 'IBMMAIL', 'MCIMAIL',
  640.             'POWERSHARE', 'PRODIGY', 'TLX', 'X400',
  641.             'GIF', 'CGM', 'WMF', 'BMP', 'MET', 'PMB', 'DIB',
  642.             'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'QTIME',
  643.             'MPEG', 'MPEG2', 'AVI',
  644.             'WAVE', 'AIFF', 'PCM',
  645.             'X509', 'PGP'
  646.         );
  647.         
  648.         // CONTENT-ID added by pmj
  649.         static $values = array (
  650.             'INLINE', 'URL', 'CID', 'CONTENT-ID'
  651.         );
  652.         
  653.         // 8BIT added by pmj
  654.         static $encodings = array (
  655.             '7BIT', '8BIT', 'QUOTED-PRINTABLE', 'BASE64'
  656.         );
  657.         
  658.         // changed by pmj to the following so that the name defaults to
  659.         // whatever the original value was.  Frank Hellwig's original
  660.         // code was "$name = 'UNKNOWN'".
  661.         $name = $value;
  662.         
  663.         if (in_array($value, $types)) {
  664.             $name = 'TYPE';
  665.         } elseif (in_array($value, $values)) {
  666.             $name = 'VALUE';
  667.         } elseif (in_array($value, $encodings)) {
  668.             $name = 'ENCODING';
  669.         }
  670.         
  671.         return $name;
  672.     }
  673.     
  674.     
  675.     /**
  676.     *
  677.     * Parses a vCard line value identified as being of the "N"
  678.     * (structured name) type-defintion.
  679.     *
  680.     * @access private
  681.     *
  682.     * @param string $text The right-part (after-the-colon part) of a
  683.     * vCard line.
  684.     * 
  685.     * @return array An array of key-value pairs where the key is the
  686.     * portion-name and the value is the portion-value.  The value itself
  687.     * may be an array as well if multiple comma-separated values were
  688.     * indicated in the vCard source.
  689.     *
  690.     */
  691.     
  692.     function _parseN($text)
  693.     {
  694.         $tmp = $this->splitBySemi($text);
  695.         return array(
  696.             $this->splitByComma($tmp[0]), // family (last)
  697.             $this->splitByComma($tmp[1]), // given (first)
  698.             $this->splitByComma($tmp[2]), // addl (middle)
  699.             $this->splitByComma($tmp[3]), // prefix
  700.             $this->splitByComma($tmp[4])  // suffix
  701.         );
  702.     }
  703.     
  704.     
  705.     /**
  706.     *
  707.     * Parses a vCard line value identified as being of the "ADR"
  708.     * (structured address) type-defintion.
  709.     *
  710.     * @access private
  711.     *
  712.     * @param string $text The right-part (after-the-colon part) of a
  713.     * vCard line.
  714.     * 
  715.     * @return array An array of key-value pairs where the key is the
  716.     * portion-name and the value is the portion-value.  The value itself
  717.     * may be an array as well if multiple comma-separated values were
  718.     * indicated in the vCard source.
  719.     *
  720.     */
  721.     
  722.     function _parseADR($text)
  723.     {
  724.         $tmp = $this->splitBySemi($text);
  725.         return array(
  726.             $this->splitByComma($tmp[0]), // pob
  727.             $this->splitByComma($tmp[1]), // extend
  728.             $this->splitByComma($tmp[2]), // street
  729.             $this->splitByComma($tmp[3]), // locality (city)
  730.             $this->splitByComma($tmp[4]), // region (state)
  731.             $this->splitByComma($tmp[5]), // postcode (ZIP)
  732.             $this->splitByComma($tmp[6])  // country
  733.         );
  734.     }
  735.     
  736.     
  737.     /**
  738.     * 
  739.     * Parses a vCard line value identified as being of the "NICKNAME"
  740.     * (informal or descriptive name) type-defintion.
  741.     *
  742.     * @access private
  743.     * 
  744.     * @param string $text The right-part (after-the-colon part) of a
  745.     * vCard line.
  746.     * 
  747.     * @return array An array of nicknames.
  748.     *
  749.     */
  750.     
  751.     function _parseNICKNAME($text)
  752.     {
  753.         return array($this->splitByComma($text));
  754.     }
  755.     
  756.     
  757.     /**
  758.     * 
  759.     * Parses a vCard line value identified as being of the "ORG"
  760.     * (organizational info) type-defintion.
  761.     *
  762.     * @access private
  763.     *
  764.     * @param string $text The right-part (after-the-colon part) of a
  765.     * vCard line.
  766.     * 
  767.     * @return array An array of organizations; each element of the array
  768.     * is itself an array, which indicates primary organization and
  769.     * sub-organizations.
  770.     *
  771.     */
  772.     
  773.     function _parseORG($text)
  774.     {
  775.         $tmp = $this->splitbySemi($text);
  776.         $list = array();
  777.         foreach ($tmp as $val) {
  778.             $list[] = array($val);
  779.         }
  780.         
  781.         return $list;
  782.     }
  783.     
  784.     
  785.     /**
  786.     * 
  787.     * Parses a vCard line value identified as being of the "CATEGORIES"
  788.     * (card-category) type-defintion.
  789.     *
  790.     * @access private
  791.     * 
  792.     * @param string $text The right-part (after-the-colon part) of a
  793.     * vCard line.
  794.     * 
  795.     * @return mixed An array of categories.
  796.     *
  797.     */
  798.     
  799.     function _parseCATEGORIES($text)
  800.     {
  801.         return array($this->splitByComma($text));
  802.     }
  803.     
  804.     
  805.     /**
  806.     * 
  807.     * Parses a vCard line value identified as being of the "GEO"
  808.     * (geographic coordinate) type-defintion.
  809.     *
  810.     * @access private
  811.     *
  812.     * @param string $text The right-part (after-the-colon part) of a
  813.     * vCard line.
  814.     * 
  815.     * @return mixed An array of lat-lon geocoords.
  816.     *
  817.     */
  818.     
  819.     function _parseGEO($text)
  820.     {
  821.         $tmp = $this->splitBySemi($text);
  822.         return array(
  823.             array($tmp[0]), // lat
  824.             array($tmp[1])  // lon
  825.         );
  826.     }
  827. }
  828.  
  829. ?>